package NG::Gen::Task::Common;
use strict;
use warnings;
use utf8;

use Data::Dumper;

use NG::Sys::Data;
use NG::Sys::App;
use NG::Sys::Datetime;

sub param {
	my $self = shift;
	unless($self->{_param}){
		$self->{_param} = array_to_hash(
				$self->{param},
				name => 'value');
	}
	return $self->{_param};
}
sub condition {
	my $self = shift;
	unless($self->{_condition}){
		my $param = $self->{proto}{condition};
		my $condition = {
				unit => array_to_hash($param->{unit}, type => 'count'),
				stat => array_to_hash($param->{stat}, check => base => mul => "add"),
				item => array_to_hash($param->{item}, type => "count"),
				level =>  $param->{level},
			};
		$self->{_condition} = $condition;
	}
	return $self->{_condition};
}
sub check_condition {
	my $self = shift;
	my $c = $self->condition;

	while(my($k,$v) = each %{$c->{unit}}){
		my $ul = $self->{leader}->units->get_by_key($k,1);
		my $c = @$ul && $ul->[0]->count;
		app()->logger->info("Unit($k): fail if $v > $c");
		if($c < $v){
			return 0;
		}
	}

	while(my($k,$v) = each %{$c->{item}}){
		my $il = $self->{leader}->items->get_by_key($k);
		app()->logger->info("Item($k): fail if $v > ".scalar(@$il));
		if(@$il < $v){
			return 0;
		}
	}

	while(my($k,$v) = each %{$c->{stat}}){
		my $has = $self->{user}->stat->$k();
		my $base = $v->[0] ? $self->{user}->stat->read_data($v->[0]) : $self->{user}->level;
		my $need;
		if($v->[1]){
			$need = int($base * $v->[0]);
		}else{
			$need = $base + ($v->[2]||0);
		}
		app()->logger->info("Stat($k):  fail if $need > $has");
		if($need > $has){
			return 0;
		}
	}
	if($c->{level} && $c->{level}{base}){
		my $has = $self->{user}->level;
		my $base = $self->{user}->stat->read_data($c->{level}{base});
		my $need;
		if($c->{level}{mul}){
			$need = int($base * $c->{level}{mul});
		}else{
			$need = $base + ($c->{level}{add}||0);
		}
		app()->logger->info("Level:  fail if $need > $has");
		if($need > $has){
			return 0;
		}
	}

	return 1;
}
sub attach_random {
	my $self = shift;

	unless($self->{proto}{events}){
		$self->{result} = "нет вариантов";
		return 0;
	}
	my @variant;
	my $total_weight = 0;
	for my $choose(1 .. 3){
		my $cb = $self->{proto}{events}{"choose".$choose};
		if($cb->{task}){
			my $param = array_to_hash(($cb->{param}||[]),name => "value");
			my $weight = $param->{weight} || 100;
			$total_weight += $weight;
			push @variant, [$total_weight,$cb,$param];
		}
	}
	my $choose;
	if($total_weight){
		my $limit = rand($total_weight);
		for(@variant){
			if($_->[0] >= $limit){
				$choose = $_;
				last;
			}
		}
	}
	app()->logger->info("variant: ".Dumper(\@variant));
	app()->logger->info("events: ".Dumper($self->{proto}{events}));
	unless($choose){
		$self->{result} = "нет вариантов";
		return 0;
	}
	my $template = NG::Gen::Task::Task->template($self->{user},$choose->[1],$choose->[2]);
	if(my $msg = $template->mutate){
		$self->{result} = $msg;
	}else{
		$self->{result} = $template->attach_template;
	}
	
	return 0;
}
sub attach_template {
	my $self = shift;
	app()->logger->info("before: ".Dumper($self->{param}));
	$self->{row}{param} = hash_to_array($self->{param},name=>"value");
	app()->logger->info("after: ".Dumper($self->{row}{param}));
	$self->{user}->ptask->insert($self->{row});
	return "Получено задание ".$self->{proto}{title};
}

sub delay {
	my $self = shift;
	return $self->param->{delay};
}
# сохраняет окружение персонажа при назначении задания
sub make_context {
	my $self = shift;
	return {};
}
sub mutate {
	my $self = shift;
	return 0;
}
sub param_on_choose {
	my $self = shift;
	return 0;
}
sub param_on_cancel {
	my $self = shift;
	return 0;
}
sub param_on_done {
	my $self = shift;
	return 0;
}
sub before_assign {
	my $self = shift;
	return 0;
}
sub after_assign {
	my $self = shift;
	return 0;
}
sub before_done {
	my $self = shift;
	return 0;
}
sub after_done {
	my $self = shift;
	$self->refresh_user(1);
	return 0;
}
sub before_cancel {
	my $self = shift;
	return 0;
}
sub after_cancel {
	my $self = shift;
	return 0;
}

1;
